home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d3 / Telnet2.6.1d3.src.sit.hqx / Telnet 2.6.1d3 source / source / main / authencrypt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-28  |  10.0 KB  |  444 lines

  1. /*
  2.  * Authencrypt.c
  3.  * Authentication module for NCSA/Telnet and Brown tn3270.
  4.  */
  5.  
  6.  
  7. #ifdef MPW
  8. #pragma segment 4
  9. #endif
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #include "TelnetHeader.h"
  15.  
  16. #include <Devices.h>
  17. #include <Files.h>
  18. #include <Folders.h>
  19. #include <GestaltEqu.h>
  20. #include <Memory.h>
  21. #include <OSUtils.h>
  22. #include <Resources.h>
  23. #include <StdLib.h>
  24. #include <Types.h>
  25.  
  26. #include "tnae.h"
  27. #include "authencrypt.h"
  28.  
  29. #include "authencrypt.proto.h"
  30.  
  31. #define NAUTHTYPES    10                    /* Max number of auth types */
  32.  
  33. struct codemodule *authmodules = 0;    /* list of authentication code modules */
  34.  
  35. static char nullbuf[] = {IAC, SB, OPT_AUTHENTICATION, TNQ_IS, AUTH_NULL, 
  36.                              AUTH_CLIENT_TO_SERVER|AUTH_HOW_ONE_WAY, IAC, SE};
  37.  
  38. #ifdef powerc
  39. enum {
  40.     uppModule = kCStackBased
  41.         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  42.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  43.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr)))
  44. };
  45. #endif
  46.  
  47. /*
  48.  * auth_encrypt_init
  49.  * Initialize processing for auth/encrypt options.
  50.  * Find all the modules that support auth/encrypt and add them to our
  51.  * typepairs and modules table. Load those modules and initialize them.
  52.  *
  53.  * Return true if any auth module found.
  54.  */
  55. Boolean auth_encrypt_init ()
  56. {
  57.     int i;
  58.     OSErr s;
  59.     short vref;
  60.     long dirid = 0, fold;
  61.     SysEnvRec theWorld;
  62.     HParamBlockRec pb;
  63.     Str255 name;
  64.  
  65.     /*
  66.      * Find and load/initialize files with code modules.
  67.      * First, Try to find the Extensions folder, else use the system folder.
  68.      */
  69.     if (Gestalt('fold', &fold)  || 
  70.         ((fold & 1) != 1) ||
  71.         FindFolder(kOnSystemDisk, kExtensionFolderType, false, &vref, &dirid)) {
  72.         if (SysEnvirons (1, &theWorld) == 0)
  73.             vref = theWorld.sysVRefNum;
  74.         else
  75.             vref = -1;
  76.     }
  77.  
  78.     for (i = 1; ; i++ ) {
  79.         pb.fileParam.ioCompletion = 0;
  80.         pb.fileParam.ioVRefNum = vref;
  81.         pb.fileParam.ioFVersNum = 0;
  82.         pb.fileParam.ioFDirIndex = i;
  83.         pb.fileParam.ioDirID = dirid;
  84.         pb.fileParam.ioNamePtr = name;
  85.         if (s = PBHGetFInfo(&pb, false))
  86.             break;
  87.  
  88.         /*
  89.          * Check for module types that we are interested in.
  90.          */
  91.         if (pb.fileParam.ioFlFndrInfo.fdType == moduleType) {
  92.             loadCode(&pb, dirid, name, authType, &authmodules);
  93.         }
  94.     }
  95.  
  96.     if (authmodules)
  97.         return true;
  98.     return false;
  99. }
  100.  
  101.  
  102. void loadCode (HParamBlockRec *pb, long dirid, Str255 name, OSType type, codemodule **header)
  103. {
  104.     int i;
  105.     short rf, oldrf;
  106.     struct codemodule *code = 0;
  107.     Handle h;
  108.  
  109.     oldrf = CurResFile();
  110.     rf = HOpenResFile(pb->fileParam.ioVRefNum, dirid, name, 0);    
  111.     if (rf == -1)
  112.         return;
  113.     SetResLoad(true);
  114.     
  115.     /*
  116.      * Find all resources of indicated type.
  117.      */
  118.     for (i = 1; ; i++) {
  119.         if (!((h = Get1IndResource(type, i))))
  120.             break;
  121.  
  122.         if (code = (struct codemodule *)NewPtrClear(sizeof(struct codemodule))) {
  123.             DetachResource(h); 
  124.             HNoPurge(h);
  125.             HLock(h);
  126.             code->entry = (module)*h;
  127.             /*
  128.              * Initialize the module.
  129.              * It should preset the type/pairs list and return the number of
  130.              * pairs entered.
  131.              */
  132. #ifdef powerc
  133.             code->npairs = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  134.                                              TNFUNC_INIT_CODE, &code->pairs);
  135.             code->encryptok = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  136.                                                 TNFUNC_QUERY_ENCRYPT, 0);
  137. #else
  138.             code->npairs = (*code->entry)(TNFUNC_INIT_CODE, &code->pairs);
  139.             code->encryptok = (*code->entry)(TNFUNC_QUERY_ENCRYPT, 0);
  140. #endif
  141.             qlink(header, code);
  142.         } else
  143.             ReleaseResource(h);
  144.     }
  145. /*    CloseResFile(rf); ddd for debugging with The Debugger ***/
  146.     UseResFile(oldrf);
  147. }
  148.  
  149.  
  150. /*
  151.  * auth_suboption
  152.  * Called by the Telnet client when an authentication sub-option is received.
  153.  * The reply option (if any) is placed into sendbuffer and *sendlength adjusted
  154.  * by the amount of data placed into sendbuffer.
  155.  */
  156. void auth_suboption (tnParams **aedata, unsigned char *subbuffer, long sublength, unsigned char *sendbuffer, unsigned long *sendlength, char *cname, Boolean hisencrypt, Boolean myencrypt)
  157. {
  158.     int i;
  159.     OSErr s;
  160.     unsigned short pair;
  161.     unsigned char *cp, *buflimit;
  162.     struct codemodule *code = 0;
  163.     tnParams *tn;                        /* temp params struct */
  164.     
  165.     buflimit = subbuffer + sublength;
  166.  
  167.     /*
  168.      * Initialize session's tnParams if not initialized yet.
  169.      * Return null auth if no memory and TNQ_SEND.
  170.      */
  171.     if (!(*aedata)) {
  172.         *aedata = (tnParams *)NewPtrClear(sizeof(tnParams));
  173.         if (!(*aedata)) {
  174.             if (subbuffer[SB_SUBOPTION] == TNQ_SEND) {
  175.                 BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  176.                 *sendlength -= sizeof(nullbuf);
  177.             }
  178.             return;
  179.         }
  180.     }
  181.     tn = *aedata;
  182.     
  183.     switch (subbuffer[SB_SUBOPTION]) {
  184.     case TNQ_IS:
  185.     case TNQ_NAME:
  186.         /* The client should not get one of these */
  187.         break;
  188.  
  189.     case TNQ_SEND:
  190.         /*
  191.          * For telnet clients, the buffer contains:
  192.          * AUTHENTICATION SEND type modifier [type modifier] [...] IAC SE
  193.          * DDD is IAC SE in the buffer???
  194.          * We scan the type/modifier pairs until we find one we can do. 
  195.          * Since they are are in priority order, the  first one we
  196.          * find that we can do wins.
  197.          */
  198.         for (cp = &subbuffer[SB_TYPE]; cp < buflimit; cp += 2) {
  199.             pair = (cp[0] << 8) | cp[1];
  200.             for (code = authmodules; code; code = code->next) {
  201.                 for (i = 0; i < code->npairs; i++)  {
  202.                     if (pair == code->pairs[i])
  203.                         goto brk;
  204.                 }
  205.             }
  206.         }
  207.     brk:
  208.         if (!code) {
  209.             /*
  210.              * If no methods match, send null authentication.
  211.              */
  212.             BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  213.             *sendlength -= sizeof(nullbuf);
  214.             return;
  215.         }
  216.  
  217.         /*
  218.          * If no auth data, initialize it now.
  219.          */
  220.         if (!(tn->authdata)) {
  221. #ifdef powerc
  222.             s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  223.                                   TNFUNC_INIT_SESSION_AUTH, &tn->authdata);
  224.             if ((s == 0) && !tn->encryptdata)
  225.                 s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  226.                                       TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  227. #else
  228.             s = (*code->entry)(TNFUNC_INIT_SESSION_AUTH, &tn->authdata);
  229.             if ((s == 0) && !tn->encryptdata)
  230.                 s = (*code->entry)(TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  231. #endif
  232.             if (s) {                    /* if no memory, etc */
  233.                 BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  234.                 *sendlength -= sizeof(nullbuf);
  235.                 return;
  236.             }
  237.             tn->entry = code->entry;
  238.         }
  239.  
  240.         /*
  241.          * Process the SEND option
  242.          */
  243.         tn->subbuffer = subbuffer;
  244.         tn->sublength = sublength;
  245.         tn->sendbuffer = sendbuffer;
  246.         tn->sendlength = sendlength;
  247.         tn->cname = cname;
  248.         tn->hisencrypt = hisencrypt;
  249.         tn->myencrypt = myencrypt;
  250. #ifdef powerc
  251.         s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  252.                               TNFUNC_AUTH_SEND, tn);        
  253. #else
  254.         s = (*tn->entry)(TNFUNC_AUTH_SEND, tn);
  255. #endif
  256.         if (s) {
  257.             /* ddd null probably wrong here ??? */
  258.             BlockMove((Ptr)nullbuf, (Ptr)sendbuffer, sizeof(nullbuf));
  259.             *sendlength -= sizeof(nullbuf);
  260.         }
  261.         return;
  262.  
  263.     case TNQ_REPLY:
  264.         /*
  265.          * Process the reply.
  266.          */
  267.         if (!(tn->authdata)) {
  268.             DebugStr("\pauth_suboption: tnq_reply no authdata");
  269.             return;
  270.         }
  271.         tn->subbuffer = subbuffer;
  272.         tn->sublength = sublength;
  273.         tn->sendbuffer = sendbuffer;
  274.         tn->sendlength = sendlength;
  275.         tn->cname = cname;
  276.         tn->hisencrypt = hisencrypt;
  277.         tn->myencrypt = myencrypt;
  278. #ifdef powerc
  279.         s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  280.                               TNFUNC_AUTH_REPLY, tn);
  281. #else
  282.         s = (*tn->entry)(TNFUNC_AUTH_REPLY, tn);
  283. #endif
  284.         switch (s) {
  285.         case TNREP_OK:
  286.             return;
  287.  
  288.         case TNREP_AUTH_OK:
  289.             break;
  290.  
  291.         case TNREP_AUTH_ERR:
  292.             break;
  293.         }
  294.         return;
  295.     }
  296. }
  297.  
  298.  
  299. /*
  300.  * encrypt_suboption
  301.  * Called by the Telnet client when an encryption sub-option is received.
  302.  * The reply option (if any) is placed into sendbuffer and *sendlength adjusted
  303.  * by the amount of data placed into sendbuffer.
  304.  */
  305. short encrypt_suboption (tnParams **aedata, unsigned char *subbuffer, long sublength, unsigned char *sendbuffer, unsigned long *sendlength, char *cname, Boolean hisencrypt, Boolean myencrypt)
  306. {
  307.     short s;
  308.     tnParams *tn;
  309.     struct codemodule *code = 0;
  310.             
  311.     /*
  312.      * Initialize session's tnParams if not there. 
  313.      * Return null auth if no memory and TNQ_SEND.
  314.      */
  315.     if (!(*aedata)) {
  316.         *aedata = (tnParams *)NewPtrClear(sizeof(tnParams));
  317.         if (!(*aedata)) {
  318.             return 0;
  319.         }
  320.     }
  321.     tn = *aedata;
  322.  
  323.     if (!tn->encryptdata) {
  324.         for (code = authmodules; code; code = code->next) {
  325.             if (code->encryptok)
  326.                 break;
  327.         }
  328.         if (!code)
  329.             return 0;
  330.  
  331. #ifdef powerc
  332.         s = CallUniversalProc((UniversalProcPtr)code->entry, uppModule, 
  333.                               TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  334. #else
  335.         s = (*code->entry)(TNFUNC_INIT_SESSION_ENCRYPT, &tn->encryptdata);
  336. #endif
  337.         if (s)
  338.             return TNREP_ERROR;
  339.  
  340.         tn->entry = code->entry;
  341.     }
  342.  
  343.     tn->subbuffer = subbuffer;
  344.     tn->sublength = sublength;
  345.     tn->sendbuffer = sendbuffer;
  346.     tn->sendlength = sendlength;
  347.     tn->cname = cname;
  348.     tn->hisencrypt = hisencrypt;
  349.     tn->myencrypt = myencrypt;
  350. #ifdef powerc
  351.     s = CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  352.                           TNFUNC_ENCRYPT_SB, tn);
  353. #else
  354.     s = (*tn->entry)(TNFUNC_ENCRYPT_SB, tn);
  355. #endif
  356.     return s;
  357. }
  358.  
  359.  
  360. unsigned char decrypt (tnParams *tn, long value)
  361. {
  362.     tn->data = value;
  363. #ifdef powerc
  364.     CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  365.                           TNFUNC_DECRYPT, tn);
  366. #else
  367.     (*tn->entry)(TNFUNC_DECRYPT, tn);
  368. #endif
  369.     return (unsigned char)tn->data;
  370. }
  371.  
  372.  
  373. void encrypt (tnParams *tn, unsigned char *buf, long len)
  374. {
  375.     tn->data = len;
  376.     tn->ebuf = buf;
  377. #ifdef powerc
  378.     CallUniversalProc((UniversalProcPtr)tn->entry, uppModule, 
  379.                           TNFUNC_ENCRYPT, tn);
  380. #else
  381.     (*tn->entry)(TNFUNC_ENCRYPT, tn);
  382. #endif
  383. }
  384.  
  385.  
  386. /*
  387.  * qlink
  388.  * Add an entry to the end of a linked list
  389.  */
  390. void qlink (void **flist, void *fentry)
  391. {
  392.     struct dummy {
  393.         struct dummy *next;
  394.     } **list, *entry;
  395.  
  396.     list = flist;
  397.     entry = fentry;
  398.     
  399.     /*
  400.      * Find address of last entry in the list.
  401.      */
  402.     while (*list)
  403.     list = &(*list)->next;
  404.  
  405.     /*
  406.      * Link entry
  407.      */
  408.     *list = entry;
  409.     entry->next = 0;
  410. }
  411.  
  412.  
  413. /*
  414.  * qunlink
  415.  * Remove an entry from linked list
  416.  * Returns the entry or NULL if not found.
  417.  */
  418. void *qunlink (void **flist, void *fentry)
  419. {
  420.     struct dummy {
  421.         struct dummy *next;
  422.     } **list, *entry;
  423.  
  424.     list = flist;
  425.     entry = fentry;
  426.     
  427.     /*
  428.      * Find entry and unlink it
  429.      */
  430.     while (*list) {
  431.         if ((*list) == entry) {
  432.             *list = entry->next;
  433.             return entry;
  434.         }
  435.     
  436.         list = &(*list)->next;
  437.     }
  438.     return NULL;
  439. }
  440.  
  441.  
  442.  
  443.  
  444.